import json
import uuid

from django.views.generic import ListView, CreateView, UpdateView, DeleteView
from django.urls import reverse_lazy
from django.shortcuts import get_object_or_404, redirect
from django.contrib import messages
from jewelry.models import Banner, Product
from jewelry.forms import BannerForm
from django.http import JsonResponse
from django.views.decorators.http import require_POST
from django.template.loader import render_to_string
from django.db.models import Q

from django.views.decorators.csrf import csrf_exempt
from django.utils.decorators import method_decorator
from rest_framework.views import APIView

from ecom.serializers.ecom.banners.serializers import BannerSerializer
from django.core.files.storage import default_storage
from rest_framework import status
from rest_framework.response import Response
from django.db import transaction, IntegrityError


# 横幅管理
class BannerListView(ListView):
    model = Banner
    template_name = 'ecom/banners/_banner_list.html'
    context_object_name = 'banners'
    paginate_by = 10

    def get_queryset(self):
        """处理搜索过滤的分页数据集"""
        queryset = super().get_queryset().order_by('-id')  # '-order',
        search_term = self.request.GET.get('search', '')

        if search_term:
            queryset = queryset.filter(title__icontains=search_term)

        # 保存搜索状态用于分页
        self.search_term = search_term
        return queryset

    def get_context_data(self, **kwargs):
        """添加完整分页信息到上下文"""
        context = super().get_context_data(**kwargs)
        page_obj = context.get('page_obj')
        paginator = page_obj.paginator if page_obj else None

        # 构建完整分页信息
        context['pagination'] = {
            'current_page': page_obj.number if page_obj else 1,
            'total_pages': paginator.num_pages if paginator else 1,
            'total_items': paginator.count if paginator else 0,
            'items_per_page': self.paginate_by,
            'has_prev': page_obj.has_previous() if page_obj else False,
            'has_next': page_obj.has_next() if page_obj else False,
            'prev_page_num': page_obj.previous_page_number() if page_obj and page_obj.has_previous() else None,
            'next_page_num': page_obj.next_page_number() if page_obj and page_obj.has_next() else None,
            'search_term': getattr(self, 'search_term', '')
        }
        return context

    def render_to_response(self, context, **response_kwargs):
        """处理AJAX分页请求"""
        if self.request.GET.get('is_ajax') or self.request.headers.get('X-Requested-With') == 'XMLHttpRequest':
            html = render_to_string(
                self.template_name,
                context,
                request=self.request
            )

            # 返回完整分页元数据
            return JsonResponse({
                'html': html,
                'pagination': context['pagination'],
                'data': {
                    'tabId': 'banners_list',
                    'stats': {
                        'visible_count': len(context['banners']),
                        'total_count': context['pagination']['total_items']
                    }
                },
                'js_files': [{
                    'type': 'esm',
                    'path': 'static/ecom/banners/js/banner_list.js',
                    'inlineCode': None
                }]
            })
        return super().render_to_response(context, **response_kwargs)


# 删除横幅
@csrf_exempt
def BannerDeleteView(request, pk):
    banner_id = pk
    # 1. 验证请求方法
    if request.method != 'POST':
        return JsonResponse({
            'errno': 405,
            'errmsg': '只允许POST请求'
        }, status=405)

    # 2. 身份验证
    api_key = request.headers.get('apiKey')
    access_token = request.headers.get('accessToken')

    if not validate_credentials(api_key, access_token):
        return JsonResponse({
            'errno': 401,
            'errmsg': '无效的API密钥或访问令牌'
        }, status=401)

    # 3. 检查横幅是否存在
    try:
        banner = Banner.objects.get(pk=banner_id)
    except Banner.DoesNotExist:
        return JsonResponse({
            'errno': 404,
            'errmsg': f'横幅ID {banner_id} 不存在或已删除'
        }, status=404)

    # 4. 业务规则验证
    # if banner.is_active:
    #     return JsonResponse({
    #         'errno': 403,
    #         'errmsg': f'横幅【{banner.title}】处于启用状态，不能删除'
    #     }, status=403)

    # 5. 删除关联资源
    if banner.image:
        try:
            banner.image.delete(save=False)  # 删除图片文件
        except Exception as e:
            # 记录错误但继续删除
            # log_error(f"删除横幅图片失败: {str(e)}")
            pass

    # 6. 执行删除
    try:
        banner.delete()
        return JsonResponse({
            'errno': 0,
            'errmsg': '删除成功',
            'data': {
                'deleted_id': banner_id,
                'title': banner.title
            }
        })
    except Exception as e:
        return JsonResponse({
            'errno': 500,
            'errmsg': f'删除失败: {str(e)}'
        }, status=500)


# 辅助函数：验证凭证
def validate_credentials(api_key, access_token):
    # 实际应用中应查询数据库或验证服务
    valid_api_keys = ["YOUR_API_KEY", "YOUR_API_KEY_2"]
    return api_key in valid_api_keys and len(access_token) > 10


# 状态启用与禁用
def toggle_banner_status(request, pk):
    banner = get_object_or_404(Banner, pk=pk)
    banner.is_active = not banner.is_active
    banner.save()
    return JsonResponse({
        'success': True,
        'is_active': banner.is_active
    })


# 优先级 (未用)
@require_POST
def update_banner_order(request, pk):
    banner = get_object_or_404(Banner, pk=pk)
    try:
        new_order = int(request.POST.get('new_order'))
        banner.order = new_order
        banner.save()

        # 重新排序所有横幅
        banners = Banner.objects.all().order_by('order')
        for index, b in enumerate(banners, start=1):
            b.order = index
            b.save(update_fields=['order'])

        return JsonResponse({'success': True})
    except Exception as e:
        return JsonResponse({'success': False, 'error': str(e)})


# 横幅创建/更新视图
class BannerCreateUpdateView(APIView):
    """横幅创建/更新视图（DRF标准实现）"""

    def post(self, request):
        """创建新横幅（自动解析JSON）"""
        serializer = BannerSerializer(data=request.data)
        if serializer.is_valid():
            banner = serializer.save()
            return Response({
                'success': True,
                'id': banner.id,
                'message': '横幅创建成功'
            }, status=status.HTTP_201_CREATED)
        return Response({
            'success': False,
            'errors': serializer.errors
        }, status=status.HTTP_400_BAD_REQUEST)

    def put(self, request, pk):
        """更新现有横幅（自动解析JSON）"""
        try:
            banner = Banner.objects.get(pk=pk)
        except Banner.DoesNotExist:
            return Response({
                'success': False,
                'message': '横幅不存在'
            }, status=status.HTTP_404_NOT_FOUND)

        serializer = BannerSerializer(banner, data=request.data, partial=True)
        if serializer.is_valid():
            serializer.save()
            return Response({
                'success': True,
                'message': '横幅更新成功'
            }, status=status.HTTP_200_OK)
        return Response({
            'success': False,
            'errors': serializer.errors
        }, status=status.HTTP_400_BAD_REQUEST)


# 横幅图片上传视图
# @method_decorator(csrf_exempt, name='dispatch')
# class BannerImageUploadView(APIView):
#     """横幅图片上传视图"""
#
#     def post(self, request):
#
#         is_new = request.POST.get('is_new') == 'true'
#         # global banner, banner_id
#         # 新增横幅处理逻辑
#         if is_new:
#             banner = Banner.objects.create(
#                 title="临时标题",
#                 is_active=0,
#                 # 其他默认值...
#             )
#             banner_id = banner.id
#             # 仅在获取必要参数后才创建记录
#             # if all([request.POST.get('title'), request.FILES.get('image')]):
#             #     banner = Banner.objects.create(
#             #         title=request.POST.get('title'),
#             #         is_active=1,  # 直接激活
#             #         image=request.FILES['image']
#             #     )
#             #     banner_id = banner.id
#             #     print('Valid banner_id:', banner_id)
#         else:
#             # 获取横幅ID
#             banner_id = request.POST.get('banner_id')
#             if not banner_id:
#                 return JsonResponse({
#                     'success': False,
#                     'message': '缺少横幅ID'
#                 }, status=400)
#
#             try:
#                 banner = Banner.objects.get(pk=banner_id)
#             except Banner.DoesNotExist:
#                 return JsonResponse({
#                     'success': False,
#                     'message': '横幅不存在'
#                 }, status=404)
#
#         # 检查是否有上传文件
#         if 'image' not in request.FILES:
#             return JsonResponse({
#                 'success': False,
#                 'message': '未提供图片文件'
#             }, status=400)
#
#         # 保存图片
#         image_file = request.FILES['image']
#
#         # 删除旧图片（如果存在）
#         if banner.image:
#             banner.image.delete(save=False)
#
#         # 生成新文件名
#         banner.image.save(
#             image_file.name,
#             image_file,
#             save=True
#         )
#
#         return JsonResponse({
#             'success': True,
#             'image_url': banner.image_url,
#             'new_banner_id': banner_id if is_new else None,  # 返回新ID
#             'message': '图片上传成功'
#         })
# 效果不佳(看要不要删除掉)
# @method_decorator(csrf_exempt, name='dispatch')
# class BannerImageUploadView(APIView):
#     def post(self, request):
#         # ===== 幂等控制 =====
#         request_id = request.POST.get('request_id')
#         print('request_id:', request_id)
#         if not request_id:
#             return JsonResponse({"error": "缺少请求ID"}, status=400)
#
#         if Banner.objects.filter(request_id=request_id).exists():
#             return JsonResponse({"error": "重复请求"}, status=409)
#
#         # ===== 业务逻辑 =====
#         is_new = request.POST.get('is_new') == 'true'
#
#         with transaction.atomic():  # 原子事务
#             if is_new:
#                 # 创建完整记录（非临时）
#                 banner = Banner.objects.create(
#                     title=request.POST['title'],
#                     is_active=1,
#                     request_id=request_id  # 关键字段
#                 )
#
#                 # 直接保存图片
#                 if 'image' in request.FILES:
#                     banner.image = request.FILES['image']
#                     banner.save()
#             else:
#                 # 更新现有记录
#                 banner = Banner.objects.get(
#                     pk=request.POST['banner_id']
#                 )
#                 if 'image' in request.FILES:
#                     # 原子化更新图片
#                     old_image = banner.image
#                     banner.image = request.FILES['image']
#                     banner.save()
#                     if old_image:
#                         old_image.delete(save=False)  # 异步删除旧图
#
#         return JsonResponse({
#             "success": True,
#             "id": str(banner.id),  # UUID格式
#             "image_url": banner.image.url
#         })


# 新的上传横幅图片
# @csrf_exempt
# @require_POST
# def upload_banner_image(request):
#     try:
#         image_file = request.FILES['image']   # request.FILES.get('image')
#         if not image_file:
#             return JsonResponse({'success': False, 'message': '未上传图片文件'})
#
#         is_new = request.POST.get('is_new') == 'true'
#         banner_id = request.POST.get('banner_id')
#         request_id = request.POST.get('request_id')
#
#         if is_new:
#             # 检查是否已存在相同request_id的临时横幅
#             banner = Banner.objects.filter(meta_data__request_id=request_id).first()
#
#             if banner:
#                 # 更新现有临时横幅
#                 banner.image = image_file
#                 banner.save()
#             else:
#                 # 创建新横幅并存储request_id
#                 banner = Banner.objects.create(
#                     title=f"新建横幅-{uuid.uuid4().hex[:6]}",
#                     image=image_file,
#                     meta_data={'request_id': request_id}  # 需要模型添加meta_data(JSONField)
#                 )
#             return JsonResponse({
#                 'success': True,
#                 'new_banner_id': banner.id,
#                 'image_url': banner.image_url
#             })
#         else:
#             try:
#                 banner = Banner.objects.get(id=banner_id)
#                 banner.image = image_file
#                 banner.save()
#                 return JsonResponse({
#                     'success': True,
#                     'image_url': banner.image_url
#                 })
#             except Banner.DoesNotExist:
#                 return JsonResponse({
#                     'success': False,
#                     'message': '指定的横幅不存在'
#                 })
#
#     except Exception as e:
#         return JsonResponse({
#             'success': False,
#             'message': f'服务器错误: {str(e)}'
#         })


# 横幅图片上传
import os
from django.core.files import locks
import logging
from django.core.cache import cache

logger = logging.getLogger(__name__)


@csrf_exempt  # 简化CSRF处理，生产环境建议用Django的csrf保护
def upload_banner_image(request):
    # 防重复提交锁
    lock_key = f"upload_lock_{request.session.session_key}"
    if cache.get(lock_key):
        return JsonResponse({"success": False, "error": "操作进行中，请稍候"}, status=429)
    cache.set(lock_key, True, timeout=5)

    try:
        # 验证请求
        if request.method != 'POST':
            return JsonResponse({'success': False, 'error': '仅支持POST请求'}, status=405)

        image_file = request.FILES.get('image')
        action = request.POST.get('is_new').lower()
        banner_id = request.POST.get('banner_id')

        if not image_file:
            return JsonResponse({'success': False, 'error': '未提供图片文件'}, status=400)

        with transaction.atomic():
            if action == 'true':
                # 原子化创建
                banner = Banner()
                banner.image.save(  # 原子化文件保存
                    image_file.name,
                    image_file,
                    save=True
                )
                message = f'新增横幅成功，ID: {banner.id}'

            elif banner_id:
                # 锁定记录+原子更新
                banner = Banner.objects.select_for_update().get(id=banner_id)
                # 先获取旧文件路径并删除
                old_image_path = banner.image.path if banner.image else None
                if old_image_path and os.path.exists(old_image_path):
                    try:
                        os.remove(old_image_path)  # 同步删除文件
                        # print(f"同步删除旧文件: {old_image_path}")
                    except Exception as e:
                        print(f"删除失败: {e}。文件可能被占用")

                # 再保存新文件
                banner.image.save(
                    image_file.name,  # 生成唯一文件名
                    image_file,
                    save=True  # 立即保存文件
                )
                banner.save()

                message = f'更新横幅成功，ID: {banner_id}'
            else:
                return JsonResponse({'success': False, 'error': '参数缺失'}, status=400)

            return JsonResponse({
                'success': True,
                'new_banner_id': banner.id,
                'image_url': banner.image_url
            })

    except IntegrityError as e:
        logger.error(f"数据完整性错误: {str(e)}")
        return JsonResponse({'success': False, 'error': '数据冲突，请重试'}, status=400)

    except Banner.DoesNotExist:
        return JsonResponse({'success': False, 'error': '横幅不存在'}, status=404)

    except OSError as e:
        logger.error(f"文件系统错误: {str(e)}")
        return JsonResponse({'success': False, 'error': '文件存储失败'}, status=500)

    except Exception as e:
        logger.exception("未处理异常")
        return JsonResponse({'success': False, 'error': '系统错误'}, status=500)

    finally:
        cache.delete(lock_key)


# 更新横幅关联商品
@csrf_exempt
def update_banner_product(request, pk):
    if request.method == 'POST':
        try:
            banner = Banner.objects.get(pk=pk)
            data = json.loads(request.body)
            product_id = data.get('product_id')

            # 更新关联商品
            if product_id:
                try:
                    product = Product.objects.get(pk=product_id)
                    banner.product = product
                    product_name = product.name
                except Product.DoesNotExist:
                    return JsonResponse({
                        'success': False,
                        'message': '商品不存在'
                    }, status=400)
            else:
                banner.product = None
                product_name = None

            banner.save()

            return JsonResponse({
                'success': True,
                'message': '关联商品已更新',
                'product_name': product_name,
                'product_id': product_id
            })

        except Banner.DoesNotExist:
            return JsonResponse({
                'success': False,
                'message': '横幅不存在'
            }, status=404)
        except Exception as e:
            return JsonResponse({
                'success': False,
                'message': f'服务器错误: {str(e)}'
            }, status=500)

    return JsonResponse({
        'success': False,
        'message': '无效的请求方法'
    }, status=405)
